import datetime
import json
import os
import requests
import cv2
from flask import make_response
from functools import wraps
from api.items import ApiResponseError, api_status_msg
from utils import get_md5_from_str


def get_current_time(fmt_str="%Y-%m-%d %H:%M:%S"):
    return datetime.datetime.now().strftime(fmt_str)


def catch_api_exception(check_type=''):
    """
    捕获api异常并组装其返回值
    :param type:
    :return:
    """

    def _handle(func):
        @wraps(func)
        def __handle(*args, **kwargs):
            errno, msg, data = -1, '', ''
            try:
                data = func(*args, **kwargs)
                if check_type == 'check_dict_result':
                    check_dict_null(data)
                errno = 10000
                msg = '请求成功'
            except ApiResponseError as e:
                are = e.extra_msg
                errno = are['code']
                msg = are['msg']
            except Exception as e:
                print(e)
                errno = api_status_msg.func_error['code']
                msg = api_status_msg.func_error['msg']
                data = str(e)
            finally:
                _res = {
                    'code': errno,
                    'msg': msg,
                    'data': data
                }

                result = make_response(json.dumps(_res, ensure_ascii=False))
                result.headers['Content-Type'] = 'application/json'
                return result

        return __handle

    return _handle


def check_dict_null(data_dict):
    if not data_dict:
        raise ApiResponseError(extra_msg=api_status_msg.error_result)
    for k, v in data_dict.items():
        if isinstance(v, list):
            check_list_null(v)
        if isinstance(v, dict):
            check_dict_null(v)
        if isinstance(v, str):
            check_str_null(v)
        if not v:
            raise ApiResponseError(extra_msg=api_status_msg.error_result)


def check_list_null(data_list):
    if not data_list:
        raise ApiResponseError(extra_msg=api_status_msg.error_result)
    for i in data_list:
        if isinstance(i, list):
            check_list_null(i)
        if isinstance(i, dict):
            check_dict_null(i)
        if isinstance(i, str):
            check_str_null(i)


def check_str_null(data_str):
    if not data_str or data_str.lower() == 'null' or data_str.lower() == 'none':
        raise ApiResponseError(extra_msg=api_status_msg.error_result)


def check_start_task_data(data):
    if isinstance(data, str):
        try:
            data = json.loads(data)
        except:
            try:
                data = eval(data)
            except:
                return False
    return data


api_validate_dict = {
    'start_visual_video_task': [{
        'check_key': 'data',
        'validate': [lambda x: isinstance(x, int)],
        'require': False,
        'call_back': lambda x: x['data']}
    ],
}


def check_request_json(func):
    @wraps(func)
    def _handle(request):
        func_name = func.__name__
        validate_list = api_validate_dict.get(func_name)
        request_params = request.json or request.args
        if validate_list:
            for v in validate_list:
                validate = v.get('validate', [])
                check_key = v.get('check_key')
                require = v.get('require')
                if check_key == 'all':
                    if callable(validate):
                        for param_key, param_value in request_params.items():
                            if not validate(param_value):
                                raise ApiResponseError(extra_msg=api_status_msg.error_params)
                else:
                    if require and not request_params.get(check_key):
                        raise ApiResponseError(extra_msg=api_status_msg.error_params)
                    if callable(validate):
                        if not validate(request_params[check_key]):
                            raise ApiResponseError(extra_msg=api_status_msg.error_params)
        return func(request)

    return _handle


def download_image_url(img_url, resize=True):
    if not img_url:
        return ''
    resouce_name = get_md5_from_str(img_url) + '.png'
    download_path = FONT_NGINX_IMAGE_PATH
    img_base64_str = requests.get(img_url, headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
                                  ' AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3573.0 Safari/537.36'}).content
    # img_data = base64.b64decode(img_base64_str)
    image_path = os.path.join(download_path, resouce_name)
    if os.path.exists(image_path):
        return image_path.replace(download_path, '../../downloadImage/').replace('\\', '/')
    else:
        with open(image_path, 'wb') as f:
            f.write(img_base64_str)
        if resize:
            try:
                image = cv2.imread(image_path)
                image = cv2.resize(image, (int(image.shape[1]), int(image.shape[1] * 9 / 16)), interpolation=cv2.INTER_CUBIC)
                cv2.imwrite(image_path, image)
            except:
                pass
        # w_h_rate = round(int(image.shape[1]) / int(image.shape[0]), 2)
        # if 16/9 > w_h_rate:
        #     image = cv2.resize(image, (1920, 1080), interpolation=cv2.INTER_CUBIC)
        #     cv2.imwrite(image_path, image)
        # else:
        #     image = cv2.resize(image, (1920, 1080), interpolation=cv2.INTER_CUBIC)
        #     cv2.imwrite(image_path, image)

        return image_path.replace(download_path, '../../downloadImage/').replace('\\', '/')

if __name__ == '__main__':
    download_image_url('https://y.gtimg.cn/music/photo_new/T002R800x800M000001qc0120J8B6D.jpg?max_age=2592000')